package com.youtills.core.crypto;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;

/**
 * Created by IntelliJ IDEA.
 * User: ravi
 * Date: 8/29/12
 * Time: 6:33 PM
 * To change this template use File | Settings | File Templates.
 */
class DES_ECB_PKCS5PaddingCipher implements ICipher{

    private static final String ALGORITHM_NAME = "DES";
    private static final String CHAR_SET_UTF8 = "UTF8";

    private static final String DEFAULT_SECRET_KEY = "$%R@v!#*";

    private final String secretKey;
    private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding";

    private final BASE64Encoder BASE_64_ENCODER = new BASE64Encoder();
    private final BASE64Decoder BASE_64_DECODER = new BASE64Decoder();

    private final Cipher encryptor;
    private final Cipher decryptor;

    DES_ECB_PKCS5PaddingCipher() {
        this(DEFAULT_SECRET_KEY);
    }

    DES_ECB_PKCS5PaddingCipher(String secretKey) {

        if(secretKey.length() < 8){
            throw new CryptoException("Secret Key for DES must have minimum 8 chracters");
        }

        this.secretKey = secretKey;

        try {

            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_NAME);
            DESKeySpec keySpec = new DESKeySpec(this.secretKey.getBytes(CHAR_SET_UTF8));
            SecretKey key = keyFactory.generateSecret(keySpec);
            this.encryptor = Cipher.getInstance(TRANSFORMATION);
            this.encryptor.init(Cipher.ENCRYPT_MODE, key);
            this.decryptor = Cipher.getInstance(TRANSFORMATION);
            this.decryptor.init(Cipher.DECRYPT_MODE, key);
        } catch (Exception e) {
            throw new CryptoException(e);
        }

    }

    public synchronized String encrypt(String plainText){
        try {
            byte[] cleartext = plainText.getBytes(CHAR_SET_UTF8);
            byte[] encrypt = encryptor.doFinal(cleartext);
            return BASE_64_ENCODER.encode(encrypt);
        } catch (UnsupportedEncodingException e) {
            throw new CryptoException(e);
        } catch (GeneralSecurityException e) {
            throw new CryptoException(e);
        }
    }

    public synchronized String decrypt(String encryptedText){
        try{
            // DECODE encryptedPwd String
            byte[] encryptedTextBytes = BASE_64_DECODER.decodeBuffer(encryptedText);
            byte[] plainTextBytes = (decryptor.doFinal( encryptedTextBytes));
            return new String(plainTextBytes, CHAR_SET_UTF8);
        }catch(GeneralSecurityException e){
            throw new CryptoException(e);
        } catch (IOException e) {
            throw new CryptoException(e);
        }
    }

    public CipherType getCypherType() {
        return CipherType.DES_ECB_PKCS5;
    }
}
